package com.adopapa.wechatapi.application.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import com.adopapa.wechatapi.domain.event.WeChatEvent;
import com.adopapa.wechatapi.domain.message.ImageRequestMessage;
import com.adopapa.wechatapi.domain.message.LinkRequestMessage;
import com.adopapa.wechatapi.domain.message.LocationRequestMessage;
import com.adopapa.wechatapi.domain.message.RequestMessage;
import com.adopapa.wechatapi.domain.message.RequestMessage.MessageType;
import com.adopapa.wechatapi.domain.message.ResponseMessage;
import com.adopapa.wechatapi.domain.message.TextRequestMessage;
import com.adopapa.wechatapi.domain.message.TextResponseMessage;
import com.adopapa.wechatapi.domain.message.VideoRequestMessage;
import com.adopapa.wechatapi.domain.message.VoiceRequestMessage;
import com.adopapa.wechatapi.util.MessageUtil;
import com.adopapa.wechatapi.xstream.XstreamUtil;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;

public class WechatCryptService {

	private final Logger logger = Logger.getLogger(WechatCryptService.class);

	/**
	 * 加密处理来自微信服务器的请求
	 * 
	 * @param request
	 * @param response
	 * @param crypt
	 * @throws Exception
	 */
	public void process(HttpServletRequest request, HttpServletResponse response, WXBizMsgCrypt crypt)
			throws Exception {
		// 微信加密签名
		String msgSignature = request.getParameter("signature");
		// 时间戳
		String timestamp = request.getParameter("timestamp");
		// 随机数
		String nonce = request.getParameter("nonce");
		logger.info("msgSignature is ".concat(msgSignature).concat(" timestamp is ").concat(timestamp)
				.concat(" nonce is ").concat(nonce));
		// 从请求中读取整个post数据
		InputStream inputStream = request.getInputStream();
		// commons.io.jar 方法
		String postData = IOUtils.toString(inputStream, "UTF-8");
		// Post打印结果
		logger.info(postData);

		String result = crypt.decryptMsg(msgSignature, timestamp, nonce, postData);
		Map<String, String> requestMap = MessageUtil.parseXml(result);
		logger.info(requestMap);

		String msgType = requestMap.get("MsgType");
		RequestMessage requestMessage = null;
		if (MessageType.image.name().equalsIgnoreCase(msgType)) {
			requestMessage = new ImageRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response, crypt);
		} else if (MessageType.link.name().equalsIgnoreCase(msgType)) {
			requestMessage = new LinkRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response, crypt);
		} else if (MessageType.location.name().equalsIgnoreCase(msgType)) {
			requestMessage = new LocationRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response, crypt);
		} else if (MessageType.text.name().equalsIgnoreCase(msgType)) {
			requestMessage = new TextRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response, crypt);
		} else if (MessageType.video.name().equalsIgnoreCase(msgType)) {
			requestMessage = new VideoRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response, crypt);
		} else if (MessageType.voice.name().equalsIgnoreCase(msgType)) {
			requestMessage = new VoiceRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response, crypt);
		} else if (MessageType.event.name().equalsIgnoreCase(msgType)) {
			WeChatEvent weChatEvent = XstreamUtil.XML2Bean(result, WeChatEvent.class);
			processEvent(weChatEvent, request, response, crypt);
		}

	}

	
	/**
	 * 处理接受事件推送
	 */
	public void processEvent(WeChatEvent weChatEvent, HttpServletRequest request, HttpServletResponse response,
			WXBizMsgCrypt crypt) throws Exception {
	}

	/**
	 * 处理接受消息
	 */
	public void processMessage(RequestMessage requestMessage, HttpServletRequest request, HttpServletResponse response,
			WXBizMsgCrypt crypt) throws Exception {
		TextResponseMessage responseMessage = new TextResponseMessage();
		responseMessage.setCreateTime(Calendar.getInstance().getTime().getTime());
		responseMessage.setFromUserName(requestMessage.getToUserName());
		responseMessage.setToUserName(requestMessage.getFromUserName());
		responseMessage.setContent("您的反馈已经记录, 谢谢您的支持!");
		sendResponseMessage(responseMessage, request, response, crypt);
	}

	/**
	 * 被动回复消息
	 * 
	 * @throws IOException
	 * @throws Exception
	 */
	public static void sendResponseMessage(ResponseMessage responseMessage, HttpServletRequest request,
			HttpServletResponse response, WXBizMsgCrypt crypt) throws Exception {
		PrintWriter out = response.getWriter();
		// 时间戳
		String timestamp = request.getParameter("timestamp");
		// 随机数
		String nonce = request.getParameter("nonce");
		String result = crypt.encryptMsg(responseMessage.toXml(), timestamp, nonce);
		out.print(result);
		out.close();
	}

}
